package com.atguigu.gmall.order.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.common.constant.MqConst;
import com.atguigu.gmall.common.service.RabbitService;
import com.atguigu.gmall.common.util.HttpClientUtil;
import com.atguigu.gmall.model.enums.OrderStatus;
import com.atguigu.gmall.model.enums.ProcessStatus;
import com.atguigu.gmall.model.order.OrderDetail;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.order.mapper.CartInfoMapper;
import com.atguigu.gmall.order.mapper.OrderDetailMapper;
import com.atguigu.gmall.order.mapper.OrderInfoMapper;
import com.atguigu.gmall.order.service.OrderInfoService;
import com.atguigu.gmall.product.client.ProductFeignClient;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author: 李旭
 * @create: 2021-09-10 16:21
 **/
@Service
public class OrderInfoServiceImpl implements OrderInfoService {

    @Value("${ware.url}")
    private String wareUrl;

    @Autowired
    private ProductFeignClient productFeignClient;
    @Autowired
    private OrderInfoMapper orderInfoMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private CartInfoMapper cartInfoMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RabbitService rabbitService;

    //连接仓库
    @Override
    public boolean hasStock(OrderDetail orderDetail) {
        return "1".equals(HttpClientUtil.doGet(
                wareUrl + "/hasStock?skuId="
                        + orderDetail.getSkuId() + "&num=" + orderDetail.getSkuNum()));
    }

    //提交订单
    @Override
    public Long saveOrder(OrderInfo orderInfo) {
        //3、保存订单表（1）  订单详情表（N）

        //3.2 订单状态
        orderInfo.setOrderStatus(OrderStatus.UNPAID.name());
        //3.3 订单交易编号 （支付宝)
        String outTradeNo = "ATGUIGU" + System.currentTimeMillis() +
                "" + new Random().nextInt(1000);
        orderInfo.setOutTradeNo(outTradeNo);
        //3.4:订单描述
        StringBuilder sb = new StringBuilder();
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();

        for (OrderDetail orderDetail : orderDetailList) {
            sb.append(orderDetail.getSkuName()).append(" ");
            //重新查询商品清单的商品的价格  实时价格
            BigDecimal price = productFeignClient.getPrice(orderDetail.getSkuId());
            orderDetail.setOrderPrice(price);
        }
        if (sb.toString().length() > 100) {
            orderInfo.setTradeBody(sb.toString().substring(0, 100));
        } else {
            orderInfo.setTradeBody(sb.toString());
        }
        //3.5创建订单的时间
        Calendar calendar = Calendar.getInstance();
        //当前时间
        orderInfo.setCreateTime(calendar.getTime());
        //未来的时间  2小时之后 不付钱 订单就取消了
        // 火车票：下了单之后 30分钟之内不付钱 订单就取消了
        calendar.add(Calendar.HOUR, 2);//2小时之后的时间
        //3.6过期时间
        orderInfo.setExpireTime(calendar.getTime());
        //3.6进度状态
        orderInfo.setProcessStatus(ProcessStatus.UNPAID.name());
        //3.1 总金额
        orderInfo.sumTotalAmount();
        //保存订单表   返回值 订单表的主键
        orderInfoMapper.insert(orderInfo);

        //库存ID 的数组或是集合
        List<String> skuIdList = new ArrayList<>();
        //保存订单详情
        for (OrderDetail orderDetail : orderDetailList) {
            orderDetail.setOrderId(orderInfo.getId());
            orderDetailMapper.insert(orderDetail);
            skuIdList.add(orderDetail.getSkuId().toString());
        }
        //4、记得删除购物车中已经购买了商品
        //4.1 DB中  批量删除   delete from cart_info where user_id = 3 and sku_id in (1,2,3)
    /*    cartInfoMapper.delete(new QueryWrapper<CartInfo>()
                .eq("user_id",orderInfo.getUserId())
                .in("sku_id",skuIdList));
        //4.2 缓存中 批量删除
        String cacheKeyCart = RedisConst.USER_KEY_PREFIX + orderInfo.getUserId()
                 + RedisConst.USER_CART_KEY_SUFFIX;
        redisTemplate.opsForHash().delete(cacheKeyCart,skuIdList.toArray());*/
        //5、 发送延迟消息 （2小时) 之后 取消订单  开始计时
  /*      rabbitService.sendDelayedMessage(MqConst.EXCHANGE_DIRECT_ORDER_CANCEL,
                MqConst.ROUTING_ORDER_CANCEL,orderInfo.getId(),MqConst.DELAY_TIME);*/
        //订单ID
        return orderInfo.getId();
    }

    //取消订单
    @Override
    public void closedOrder(Long orderId) {

        //orderInfoMapper.updateById()// update order_info set order_status = closed  where ..
        //1:先查询     幂等性问题：用户已经付完钱了  订单的状态已经由原来的未支付 改成已支付
        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
        if (null != orderInfo && orderInfo.getOrderStatus().equals(OrderStatus.UNPAID.name())) {
            //确实 是未支付 关闭吧
            orderInfo.setOrderStatus(OrderStatus.CLOSED.name());
            //2:更新订单及进度的状态
            orderInfo.setProcessStatus(ProcessStatus.CLOSED.name());
            orderInfoMapper.updateById(orderInfo);

        }

    }

    //查询订单对象
    @Override
    public OrderInfo getOrderInfo(Long orderId) {
        return orderInfoMapper.selectById(orderId);

    }

    //查询订单对象及订单详情集合
    public OrderInfo getOrderInfoAndDetail(Long orderId) {
        OrderInfo orderInfo = getOrderInfo(orderId);
        orderInfo.setOrderDetailList(orderDetailMapper.selectList(new QueryWrapper<OrderDetail>()
                .eq("order_id", orderId)));
        return orderInfo;
    }

    // 通用 更新订单状态
    public void updateOrderStatus(Long orderId, ProcessStatus processStatus) {
        OrderInfo orderInfo = getOrderInfo(orderId);
        orderInfo.setOrderStatus(processStatus.getOrderStatus().name());
        orderInfo.setProcessStatus(processStatus.name());
        orderInfoMapper.updateById(orderInfo);
    }

    // 通用 更新订单状态
    public void updateOrderStatus(OrderInfo orderInfo, ProcessStatus processStatus) {
        orderInfo.setOrderStatus(processStatus.getOrderStatus().name());
        orderInfo.setProcessStatus(processStatus.name());
        orderInfoMapper.updateById(orderInfo);
    }

    //代码巅峰   拆单
    @Override
    public List<OrderInfo> orderSplit(Long orderId, String wareSkuMap) {
        //wareSkuMap: [{"wareId":"2","skuIds":["15"]},{"wareId":"1","skuIds":["7"]}]

        //原始订单 父订单
        OrderInfo originOrderInfo = getOrderInfoAndDetail(orderId);
        //拆分成多个子订单
        List<Map> wareSkuMapList = JSONObject.parseArray(wareSkuMap, Map.class);
        List<OrderInfo> subOrderInfoList = wareSkuMapList.stream().map(wareMap -> {
            //子订单
            OrderInfo subOrderInfo = new OrderInfo();
            BeanUtils.copyProperties(originOrderInfo, subOrderInfo);
            //ID
            subOrderInfo.setId(null);
            //仓库ID
            subOrderInfo.setWareId(String.valueOf(wareMap.get("wareId")));
            //父ID
            subOrderInfo.setParentOrderId(originOrderInfo.getId());
            //原始订单详情 集合
            List<OrderDetail> originOrderDetailList = originOrderInfo.getOrderDetailList();
            //子订单详情集合
            List<OrderDetail> subOrderDetailList = new ArrayList<>();
            //wareSkuMap: [{"wareId":"2","skuIds":["15"]},{"wareId":"1","skuIds":["7"]}]
            Map<String, OrderDetail> originDetailMap = originOrderDetailList.stream().collect(
                    Collectors.toMap(orderDetail -> orderDetail.getSkuId().toString(),
                            orderDetail -> orderDetail));
            List<String> skuIds = (List<String>) wareMap.get("skuIds");
            for (String skuId : skuIds) {
                OrderDetail orderDetail = originDetailMap.get(skuId);
                if (null != orderDetail) {
                    subOrderDetailList.add(orderDetail);
                }
            }
            subOrderInfo.setOrderDetailList(subOrderDetailList);
            //金额
            subOrderInfo.sumTotalAmount();
            //保存子订单到DB中
            orderInfoMapper.insert(subOrderInfo);
            //子订单详情集合
            for (String skuId : skuIds) {
                OrderDetail orderDetail = originDetailMap.get(skuId);
                if (null != orderDetail) {
                    orderDetail.setOrderId(subOrderInfo.getId());
                    orderDetailMapper.updateById(orderDetail);
                }
            }
            //更新订单的状态  同学此处可以更改批量
            updateOrderStatus(subOrderInfo, ProcessStatus.SPLIT);
            return subOrderInfo;
        }).collect(Collectors.toList());

        return subOrderInfoList;
    }

    //更新订单的状态  未支付更新已支付
    @Override
    public void updateOrderStatusPaid(Long orderId, ProcessStatus processStatus) {
        //1:幂等性问题
        OrderInfo orderInfo = getOrderInfo(orderId);
        //是未支付吗？  更新已支付      已支付 待发货
        //2:
        if (null != orderInfo && orderInfo.getOrderStatus().equals(OrderStatus.UNPAID.name())) {
            //更新订单状态
            updateOrderStatus(orderInfo, processStatus);
            //发消息MQ 给仓库系统  （库存系统）
            rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_WARE_STOCK,
                    MqConst.ROUTING_WARE_STOCK,
                    JSONObject.toJSONString(initWareOrder(orderId)));
            //订单进度状态的更新
            updateOrderStatus(orderInfo, ProcessStatus.NOTIFIED_WARE);

        }
    }
    //初始化仓库所需要的数据
    public Map initWareOrder(OrderInfo orderInfo){
        Map map = new HashMap();
        map.put("orderId", orderInfo.getId());
        map.put("consignee", orderInfo.getConsignee());
        map.put("consigneeTel", orderInfo.getConsigneeTel());
        map.put("orderComment", orderInfo.getOrderComment());
        map.put("orderBody", orderInfo.getTradeBody());
        map.put("deliveryAddress", orderInfo.getDeliveryAddress());
        map.put("wareId", orderInfo.getWareId());//附加字段
        map.put("paymentWay",
                orderInfo.getPaymentWay().equalsIgnoreCase("ONLINE") ? "2" : "1");

        List<Map> listMap = orderInfo.getOrderDetailList().stream().map(orderDetail -> {
            Map m = new HashMap();
            m.put("skuId", orderDetail.getSkuId());
            m.put("skuNum", orderDetail.getSkuNum());
            m.put("skuName", orderDetail.getSkuName());
            return m;
        }).collect(Collectors.toList());
        map.put("details", listMap);
        return map;
    }
    //初始化仓库所需要的数据
    public Map initWareOrder(Long orderId) {
        OrderInfo orderInfo = getOrderInfoAndDetail(orderId);
        return initWareOrder(orderInfo);
    }


}
